package com.bo.baby2.service.impl;

import com.bo.baby2.config.ReturnResult;
import com.bo.baby2.dao.*;
import com.bo.baby2.entity.*;
import com.bo.baby2.service.BidService;
import com.bo.baby2.tools.CalculationInterest;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

/**
 * @program: baby2_p2p
 * @description:
 * @author:波
 * @create: 2020-07-18 19:00
 **/
@Service

public class BidServiceImpl implements BidService {
    @Resource
    private TBidMapper tBidMapper;
    @Resource
    private TBorrowMapper tBorrowMapper;
    @Resource
    private TUserWalletMapper tUserWalletMapper;
    @Resource
    private TAccountFlowMapper tAccountFlowMapper;
    @Resource
    private TRepaymentMapper tRepaymentMapper;
    @Resource
    private TRepaymentDetailMapper tRepaymentDetailMapper;
    /**
     * 根据借款id查询投标记录
     * @param borrowId
     * @return
     */
    @Override
    public List<TBid> getBidByBorrowId(String borrowId) {
        return tBidMapper.getBidByBorrowId(borrowId);
    }

    /**
     * 投标的方法
     * @param bid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object addBorrowBid(TBid bid) {
        //先查询出当前账号可用余额
        TUserWallet tUserWallet = tUserWalletMapper.selectByPrimaryKey(bid.getBidUserId());
        //根据借款id查询出借款标的信息
        TBorrow tBorrow = tBorrowMapper.selectByPrimaryKey(bid.getBorrowId());

        //用户只能对招标中的标的进行投标
        if(!tBorrow.getBorrowState().equals(20)){
            return ReturnResult.failResult("该标的状态不是招标中");

        }        //如果投标金额大于可用余额就提示账户余额不足
        if(tUserWallet.getAvailableAmount()<bid.getBidAmount()){
            return ReturnResult.failResult("账户余额不足");
        }
        //用户不能投标自己的标的
        if(bid.getBidUserId().equals(tBorrow.getBorrowUserId())){
            return ReturnResult.failResult("不能投自己的标");
        }
        //投标金额必须大于50，并且是50的倍数
        if(bid.getBidAmount()<5000||bid.getBidAmount()%50!=0){
            return ReturnResult.failResult("投标金额不能小于50或不是50的倍数");
        }
        //如果你投资金额大于借款金额
        if(bid.getBidAmount()>tBorrow.getBorrowAmount()){
            return ReturnResult.failResult("操作失败");
        }
        //如果招标截止时间小于当时间，就说明流标了
        if(tBorrow.getBidDeadline().compareTo(LocalDateTime.now())<0){
            liubiao();
            return ReturnResult.failResult("该标的已流标");
        }

        int insertBid=0;
        int updateBid=0;
        //判断用户是否是第二次投标，如果是第一次就新增一条投标信息，如果是第二次投标就进行修改投标信息
        TBid bidByUserId = tBidMapper.getBidByUserId(bid.getBidUserId(),bid.getBorrowId());
        //求出当前投标利息
        Long interest = Long.parseLong(CalculationInterest.calculationInterest(bid.getBidAmount(), tBorrow.getYearRate(), tBorrow.getRepaymentMonth(), tBorrow.getRepaymentType()).toString());
        if(bidByUserId==null) {

            /* if()*/
            bid.setId(UUID.randomUUID().toString().replace("-", ""));
            bid.setBidTime(LocalDateTime.now());
            bid.setBorrowTitle(tBorrow.getTitle());
           /* //如果投标金额加上已投标金额等于借款总金额就修改状态为放款审核中,否则就是招标中
            Long sumAmount = bid.getBidAmount() + tBorrow.getCurrentBidAmount();
            if (sumAmount.equals(tBorrow.getBorrowAmount())) {
                bid.setBorrowState(30);
            }*/
            bid.setBorrowState(30);
            bid.setYearRate(tBorrow.getYearRate());
            bid.setBidInterest(interest);
             insertBid = tBidMapper.insertSelective(bid);
        }else {
            bidByUserId.setBidAmount(bidByUserId.getBidAmount()+bid.getBidAmount());
            bidByUserId.setBidInterest(bidByUserId.getBidInterest()+interest);
             updateBid=tBidMapper.updateByPrimaryKeySelective(bidByUserId);
        }
        if(insertBid>0||updateBid>0) {
            //如果投标金额加上已投标金额等于借款总金额就修改状态为放款审核中
            Long sumAmount = bid.getBidAmount() + tBorrow.getCurrentBidAmount();
            if (sumAmount.equals(tBorrow.getBorrowAmount())) {
                tBorrow.setBorrowState(30);
            }
            //投标成功后同时修改借款标的信息
            tBorrow.setBidNum(tBorrow.getBidNum() + 1);       //已投标数量
            tBorrow.setCurrentBidAmount(tBorrow.getCurrentBidAmount() + bid.getBidAmount());  //当前已投标金额
            tBorrow.setCurrentBidInterest(tBorrow.getCurrentBidInterest() + interest); //当前已投标利息

            int updateBorrow = tBorrowMapper.updateByPrimaryKeySelective(tBorrow);
            //投标成功后，还要同时修改投标用户账号里的可用余额和冻结额度
            tUserWallet.setAvailableAmount(tUserWallet.getAvailableAmount() - bid.getBidAmount());    //可用金额
            tUserWallet.setFreezeAmount(tUserWallet.getFreezeAmount()+bid.getBidAmount());    //冻结金额
           /* tUserWallet.setInterestPending(tUserWallet.getInterestPending()+interest);      //待收利息
            tUserWallet.setPrincipalPending(tUserWallet.getPrincipalPending()+bid.getBidAmount());    //待收本金*/
            int updateWallet = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet);
            if(updateBorrow>0&&updateWallet>0){
                return ReturnResult.successResult("成功",null);
            }else {
                return ReturnResult.failResult("投标失败2");
            }
        }else {
            return ReturnResult.failResult("投标失败");
        }
    }

    /**
     * 流标的方法
     */
    @Transactional(rollbackFor = Exception.class)
    @Scheduled(fixedRate = 30000)
    public void liubiao(){
        List<TBorrow> borrows = tBorrowMapper.getBorrows();
        for (TBorrow borrow:borrows) {
            LocalDateTime now = LocalDateTime.now();
            Duration between = Duration.between(now,borrow.getBidDeadline()); //获取两个时间的时间差
            long l = between.toMillis();    //获取相差的毫秒数
            //如果招标截止日期小于当前时间说明过期
            if(l<=0){
                //流标
                //根据他的借款标的id出他的投标信息，然后修改投标人的资金账户信息和退回借款人的授信额度和修改标的招标状态
                //查询借款人的信息
                TUserWallet tUserWallet1 = tUserWalletMapper.selectByPrimaryKey(borrow.getBorrowUserId());
                tUserWallet1.setResidualCreditLine(tUserWallet1.getResidualCreditLine()+borrow.getBorrowAmount());
                //退回借款人剩余授信额度
                int i2 = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet1);
                //修改借款标的状态
                borrow.setBorrowState(21);
                int i3 = tBorrowMapper.updateByPrimaryKeySelective(borrow);
                List<TBid> bidByBorrowId = tBidMapper.getBidByBorrowId(borrow.getId());
                for (TBid bid: bidByBorrowId) {
                    //查询投标人的信息
                    TUserWallet tUserWallet=tUserWalletMapper.selectByPrimaryKey(bid.getBidUserId());
                    tUserWallet.setAvailableAmount(tUserWallet.getAvailableAmount()+bid.getBidAmount());    //可用金额
                    /*tUserWallet.setInterestPending(tUserWallet.getInterestPending()-bid.getBidInterest());      //待收利息
                    tUserWallet.setPrincipalPending(tUserWallet.getPrincipalPending()-bid.getBidAmount());      //待收本金*/
                    tUserWallet.setFreezeAmount(tUserWallet.getFreezeAmount()-bid.getBidAmount());      //冻结金额
                    //退回投标人资金
                    int i = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet);
                    //生成一条退款流水
                    TAccountFlow tAccountFlow=new TAccountFlow();
                    tAccountFlow.setAccountId(tUserWallet.getAccountId());
                    tAccountFlow.setAmount(bid.getBidAmount());
                    tAccountFlow.setAvailableAmount(tUserWallet.getAvailableAmount());
                    tAccountFlow.setFreezeAmount(tUserWallet.getFreezeAmount());
                    tAccountFlow.setRemark("投标失败，"+bid.getBorrowTitle()+"标的已流标，退款金额："+bid.getBidAmount());
                    tAccountFlow.setFlowType(21);
                    int i1 = tAccountFlowMapper.insertSelective(tAccountFlow);
                    bid.setBorrowState(21);
                    tBidMapper.updateByPrimaryKeySelective(bid);
                    if(i>0&&i1>0){
                        System.out.println("流标成功："+bid.getBorrowTitle()+"标的，已流标");
                    }
                }
            }
            System.out.println(l);
        }
    }

    /**
     * 满标审核的方法
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ReturnResult borrowAudit(String borrowId,Integer borrowState){
        //根据借款id查询出投标人信息
        List<TBid> bidByBorrowId = tBidMapper.getBidByBorrowId(borrowId);
        //查询出借款标的信息
        TBorrow tBorrow = tBorrowMapper.selectByPrimaryKey(borrowId);

        //放款审核拒绝的时候,退回投标人投标金额，并生成一个退款流水,在退回借款人账户的授信的
        if(borrowState.equals(31)){
            for (TBid bid:bidByBorrowId) {
                //根据投标人id出投标人信息，然后修改投标人账户金额
                TUserWallet tUserWallet=tUserWalletMapper.selectByPrimaryKey(bid.getBidUserId());
                tUserWallet.setAvailableAmount(tUserWallet.getAvailableAmount()+bid.getBidAmount());    //可用金额
                tUserWallet.setFreezeAmount(tUserWallet.getFreezeAmount()-bid.getBidAmount());      //冻结金额

                //退回投标人资金
                int i = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet);
                //生成一条退款流水
                TAccountFlow tAccountFlow=new TAccountFlow();
                tAccountFlow.setAccountId(tUserWallet.getAccountId());
                tAccountFlow.setAmount(bid.getBidAmount());
                tAccountFlow.setAvailableAmount(tUserWallet.getAvailableAmount());
                tAccountFlow.setFreezeAmount(tUserWallet.getFreezeAmount());
                tAccountFlow.setRemark("投标失败，"+bid.getBorrowTitle()+"标的审核失败，退款金额："+bid.getBidAmount()*0.01);
                tAccountFlow.setFlowType(21);
                int i1 = tAccountFlowMapper.insertSelective(tAccountFlow);

                bid.setBorrowState(31);
                tBidMapper.updateByPrimaryKeySelective(bid);
            }
            //然后修改投标人的资金账户信息和退回借款人的授信额度和修改标的招标状态
            //查询借款人的信息
            TUserWallet tUserWallet1 = tUserWalletMapper.selectByPrimaryKey(tBorrow.getBorrowUserId());
            tUserWallet1.setResidualCreditLine(tUserWallet1.getResidualCreditLine()+tBorrow.getBorrowAmount());
            //退回借款人剩余授信额度
            int i2 = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet1);
            //修改借款标的状态
            tBorrow.setBorrowState(31);
            int i3 = tBorrowMapper.updateByPrimaryKeySelective(tBorrow);
            if(i3>0&&i2>0){
                return ReturnResult.successResult("成功",null);
            }else {
                return  ReturnResult.failResult("审核失败");
            }
            //放款审核通过的情况
        }else if(borrowState.equals(32)){
            //审核通过将借款的钱到借款人账户中，修改账待还金额
            TUserWallet tUserWallet = tUserWalletMapper.selectByPrimaryKey(tBorrow.getBorrowUserId());
            tUserWallet.setAvailableAmount(tUserWallet.getAvailableAmount()+tBorrow.getBorrowAmount()); //可用金额
            tUserWallet.setRepaidAmount(tBorrow.getBorrowAmount()+tBorrow.getTotalInterest());    //代还金额
            int i = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet);
            //修改成功之后生成一条流水
            TAccountFlow tAccountFlow=new TAccountFlow();
            if(i>0){
                tAccountFlow.setAccountId(tBorrow.getBorrowUserId());
                tAccountFlow.setAmount(tBorrow.getBorrowAmount());
                tAccountFlow.setAvailableAmount(tUserWallet.getAvailableAmount());
                tAccountFlow.setFreezeAmount(tUserWallet.getFreezeAmount());
                tAccountFlow.setFlowType(10);
                tAccountFlow.setRemark("借款成功，"+tBorrow.getBorrowAmount()+"已存入账户");
                tAccountFlowMapper.insertSelective(tAccountFlow);
            }
            //为每位投资人生成一条投资流水,修改每位投标人的资金账户
            for (TBid tBid:bidByBorrowId) {

                TUserWallet tUserWallet1 = tUserWalletMapper.selectByPrimaryKey(tBid.getBidUserId());
                tUserWallet1.setFreezeAmount(tUserWallet1.getFreezeAmount()-tBid.getBidAmount());   //冻结金额
                tUserWallet1.setInterestPending(tUserWallet1.getInterestPending()+tBid.getBidInterest());//代收利息
                tUserWallet1.setPrincipalPending(tUserWallet1.getPrincipalPending()+tBid.getBidAmount());//待收本金
                int i1 = tUserWalletMapper.updateByPrimaryKeySelective(tUserWallet1);
                TAccountFlow tAccountFlow2=new TAccountFlow();
               tAccountFlow2.setAccountId(tUserWallet1.getAccountId());
               tAccountFlow2.setAmount(tBid.getBidAmount());
               tAccountFlow2.setAvailableAmount(tUserWallet1.getAvailableAmount());
               tAccountFlow2.setFreezeAmount(tUserWallet1.getFreezeAmount());
               tAccountFlow2.setFlowType(20);
               tAccountFlow2.setRemark("投标成功，投标金额："+tBid.getBidAmount());
               tAccountFlowMapper.insertSelective(tAccountFlow2);
            }
            int insertRepayment=0;
            int insertRepaymentDetail=0;
            //转换本金总金额
            BigDecimal borrowAmount2=new BigDecimal(String.valueOf(tBorrow.getBorrowAmount()));
            //在计算月利率
            BigDecimal monthRate=new BigDecimal(String.valueOf(tBorrow.getYearRate()))
                    .divide(new BigDecimal(String.valueOf(12)),4,BigDecimal.ROUND_HALF_UP)
                    .divide(new BigDecimal(String.valueOf(100)));
            //获取总利息
            Long aLong = tBorrow.getTotalInterest();
            //每月平均还款    (本金+总利息)/还款周期
            BigDecimal avgmothod= borrowAmount2.add(new BigDecimal(String.valueOf(aLong))).divide(new BigDecimal(String.valueOf(tBorrow.getRepaymentMonth())),4,BigDecimal.ROUND_HALF_UP);
            double bj=borrowAmount2.doubleValue();      //变动的本金

            //根据借款标的分期期数，创建对应期数的还款计划
            Integer repaymentMonth = tBorrow.getRepaymentMonth();   //拿到期数
            for(int z=0;z<repaymentMonth;z++){
                TRepayment tRepayment=new TRepayment();
                tRepayment.setId(UUID.randomUUID().toString().replace("-","")); //id
                tRepayment.setBorrowId(tBorrow.getId());    //借款ID
                tRepayment.setBorrowTitle(tBorrow.getTitle());  //借款标题
                tRepayment.setBorrowUserId(tBorrow.getBorrowUserId());//借款人id
                tRepayment.setRepaymentTime(LocalDateTime.now().plusMonths((z+1)));//还款日期
                tRepayment.setDeadline(LocalDateTime.now().plusMonths(1).plusMonths(z));//截止日期
                tRepayment.setPeriod(z+1);//还款期数
                tRepayment.setState(2);      //还款状态
                tRepayment.setBorrowType(tBorrow.getBorrowType()); //借款类型
                tRepayment.setRepaymentType(tBorrow.getBorrowType());   //还款方式
                // TODO: 2020-07-23 待算借款人每期本金和利息
                BigDecimal bj2 = new BigDecimal(String.valueOf(bj));
                //每月还款利息  本金*月利率
                BigDecimal yuelix = bj2.multiply(new BigDecimal(String.valueOf(monthRate))).divide(new BigDecimal(String.valueOf(100)),4, BigDecimal.ROUND_HALF_UP);

                BigDecimal yuelix2 = yuelix.multiply(new BigDecimal(String.valueOf(100)));
                //每月还款本金 每月平均还款-月利息
                BigDecimal subtract1 = avgmothod.subtract(yuelix2);
                //剩余本金  本金-每月还款本金
                BigDecimal subtract = bj2.subtract(subtract1);
                //还款总金额
                BigDecimal totalAmount = yuelix2.add(subtract1);
                //最后在将剩余本金赋值给本金
                bj = subtract.doubleValue();
                tRepayment.setPrincipal(subtract1.doubleValue()); //每月还款本金
                tRepayment.setInterest(yuelix2.doubleValue());     //每月还款利息
                tRepayment.setTotalAmount(totalAmount.longValue()); //每月还款总金额
                insertRepayment = tRepaymentMapper.insertSelective(tRepayment);      //新增还款计划表
                //根据借款标的每位投资人的投标金额，为每位投资人创建对应的还款计划明细，包含每月应收的本金和利息
                for (TBid tbid:bidByBorrowId) {
                    //根据每期生成每位投资人的每月的收款计划明细
                    TRepaymentDetail tRepaymentDetail = new TRepaymentDetail();
                    tRepaymentDetail.setId(UUID.randomUUID().toString().replace("-", ""));
                    tRepaymentDetail.setBidId(tbid.getId());      //标的id
                    tRepaymentDetail.setBorrowId(tBorrow.getId());   //借款id;
                    tRepaymentDetail.setRepaymentId(tRepayment.getId());       //还款Id;
                    tRepaymentDetail.setBorrowUserId(tBorrow.getBorrowUserId());      //借款人Id
                    tRepaymentDetail.setBidUserId(tbid.getBidUserId());  //投标人Id
                    tRepaymentDetail.setBorrowTitle(tBorrow.getTitle()); //借款标题
                    BigDecimal repaymentMo = new BigDecimal(String.valueOf(repaymentMonth));
                    BigDecimal  principal= new BigDecimal(String.valueOf(tbid.getBidAmount())).divide(new BigDecimal(String.valueOf(100))).divide(repaymentMo,4,BigDecimal.ROUND_HALF_UP); //求出本金
                    BigDecimal Interest = new BigDecimal(String.valueOf(tbid.getBidInterest())).divide(new BigDecimal(String.valueOf(100))).divide(repaymentMo,4,BigDecimal.ROUND_HALF_UP);//求出利息
                    BigDecimal principal2 = principal.multiply(new BigDecimal(String.valueOf(100)));
                    BigDecimal Interest2 = Interest.multiply(new BigDecimal(String.valueOf(100)));
                    tRepaymentDetail.setPrincipal(principal2.doubleValue());        //本期还款本金
                    tRepaymentDetail.setInterest(Interest2.doubleValue()); //本期还款总利息
                    tRepaymentDetail.setTotalAmount(tRepaymentDetail.getPrincipal() + tRepaymentDetail.getInterest()); //本期还款总金额(利息+本金)
                    // TODO: 2020-07-23 待算投资人待收本金和利息
                    tRepaymentDetail.setPeriod(tRepayment.getPeriod());        //还款期数
                    tRepaymentDetail.setDeadline(tRepayment.getDeadline());         //本期还款截止日期
                    tRepaymentDetail.setRepaymentType(tRepayment.getRepaymentType());   //本期还款方式
                    tRepaymentDetail.setRepaymentTime(tRepayment.getRepaymentTime());//还款日期
                    insertRepaymentDetail = tRepaymentDetailMapper.insertSelective(tRepaymentDetail);
                }
            }
           /* i=i/0;*/
            if (insertRepayment>0&&insertRepaymentDetail>0){
                //更新标的状态为'还款中'
                for (TBid tbid:bidByBorrowId) {
                    tbid.setBorrowState(40);
                    tBidMapper.updateByPrimaryKeySelective(tbid);
                }
                tBorrow.setBorrowState(40);
                int i1 = tBorrowMapper.updateByPrimaryKeySelective(tBorrow);
                if(i1>0){
                    return ReturnResult.successResult("",null);
                }else {
                    return ReturnResult.failResult("审核失败3");
                }
            }else {
                return ReturnResult.failResult("审核失败2");
            }

        }else{
            return ReturnResult.failResult("审核失败");
        }
    }

    /**
     * 查询投标信息
     * @param borrowQuery
     * @return
     */
    @Override
    public List<TBid> getBids(BorrowQuery borrowQuery) {
        return tBidMapper.getBids(borrowQuery);
    }

    /**
     * 查询总数量
     * @param borrowQuery
     * @return
     */
    @Override
    public int getCount(BorrowQuery borrowQuery) {
        return tBidMapper.getCount(borrowQuery);
    }
}
